We are using the SHIVA trial to run a retrospective analysis to validate the PTD package. During the trial, the hormon receptors ER, AR and PR were colelcted using Immunohistochemistry (IHC). In the retrospective analisi we used the expression (as z-score) values collected from the RNA-seq data TCGA dataset. In this section we want to explore the relationship between RNA-seq and Immunohistochemistry and, possibly, identify a “entrance” threshold that we can use in the simulation.
!!!EXPLAIN BETTER HERE!!!
Comparative analysis
To run the comparison analysis we will need two datasets:
- Dataset with IHC values,
- Dataset with RNA-seq expresison values
Both dataset need to have in common the same patients so that we can reconstruct the index.
The analysis will be run on two hormon receptos:
ER analysis
IHC dataset
As Input dataset we are choosing to use:
Clinical data downloaded from cBioportal for the dataset: Breast Invasive Carcinoma (TCGA, Cell 2015) - LINK
The dataset has been downloade and stored as brca_tcga_pub2015_clinical_data.tsv.
library(dplyr)
library(ggplot2)
library(plotly)
library(readr)
library(knitr)
ihc <-readr::read_tsv("../external_resources/brca_tcga_pub2015_clinical_data.tsv")
ihcFilter <- ihc %>%
dplyr::select(`Patient ID`
#, `Sample ID`
, `ER Status By IHC`
, `ER Status IHC Percent Positive`
#, `ER positivity scale used`
#, `ER positivity scale other`
#, `IHC Score`
#, `IHC-HER2`
#, `PR positivity scale used`
#, `PR status by ihc`
#, `PR status ihc percent positive`
) %>%
dplyr::filter(!is.na(`ER Status By IHC`)) %>% # Remove the <NA>
dplyr::filter(!is.na(`ER Status IHC Percent Positive`)) %>% # Remove the <NA>
dplyr::rename(case_id=`Patient ID`, er_status=`ER Status By IHC`, ihc_value=`ER Status IHC Percent Positive`)
# preview
kable(head(ihcFilter), caption="top 6 rows")
| TCGA-A2-A3XV |
Positive |
<10% |
| TCGA-A2-A3Y0 |
Positive |
90-99% |
| TCGA-LL-A50Y |
Positive |
90-99% |
| TCGA-LL-A5YP |
Positive |
<10% |
| TCGA-LL-A5YL |
Positive |
90-99% |
| TCGA-LL-A5YM |
Positive |
90-99% |
RNA-seq dataset
The RNA-seq dataset was extracted using PTD function.!
| TCGA-A1-A0SB |
-0.9404 |
| TCGA-A1-A0SD |
-0.1790 |
| TCGA-A1-A0SE |
-0.6355 |
| TCGA-A1-A0SF |
-0.3363 |
| TCGA-A1-A0SH |
-0.9036 |
| TCGA-A1-A0SI |
-0.6584 |
Inner Join datasets
df <- dplyr::inner_join(rnaseq, ihcFilter, by="case_id")
DT::datatable(df
# ADD BUTTONS TO THE TABLE
, extensions = 'Buttons'
, options = list(
dom = 'lBfrtip'
, buttons = c('copy', 'csv', 'excel')
)
, caption = "Comparison between Missing and Submitted regions (bp) in the panel"
)
Comparison Analysis
Explore RNA-seq Z-score
# explore z-score value
p1 <- ggplot(df, aes(x=expressionValue)) +
geom_density(kernel="gaussian") +
geom_vline(aes(xintercept=0.3, color="red")) +
labs(x="Expression z-scores", title="Rna-seq expression density plot") +
theme(legend.position = "none", plot.title=element_text(size=10))
p1

Explore ICH values
# barplot
p2 <- ggplot(data=df, aes(x=ihc_value)) +
geom_bar(stat = "count", position = "stack") +
labs(title="Barplot with COUNT of patients in each ER ICH expression value (from 0 to 100%)")+
theme(legend.position = "none", plot.title=element_text(size=10))
p2

Compare
p3 <- ggplot(data=df, aes(x=ihc_value, y=expressionValue, group=1)) +
geom_point(colour="red", size=1, shape=21, fill="white") +
labs(title="Comparison between RNA-seq and IHC values for ER in Breast cancer") +
xlab("IHC value") +
ylab("RNA-seq z-score") +
geom_smooth(method="lm") +
geom_hline(yintercept =0.3) +
theme(legend.position = "none", plot.title=element_text(size=10))
ggplotly(p3,width = 650, height = 400, margin(t=1000))
Fit to a linear model
# Convert chategorical values to continue numerical value
# <10% = 1
# 10-19% = 2
# etc..
df$ihc_value2 <- as.numeric(factor(df$ihc_value))
# Fit the data into a linea regressino model ache chek the coefficients
summary(lm(df$expressionValue ~ ihc_value2, df))
Call:
lm(formula = df$expressionValue ~ ihc_value2, data = df)
Residuals:
Min 1Q Median 3Q Max
-1.1511 -0.5160 -0.1985 0.3118 3.6848
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.91121 0.10598 -8.598 4.32e-16 ***
ihc_value2 0.10991 0.01292 8.510 7.99e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.7788 on 305 degrees of freedom
Multiple R-squared: 0.1919, Adjusted R-squared: 0.1892
F-statistic: 72.42 on 1 and 305 DF, p-value: 7.986e-16
There is a significant linear relationship between the predictor and the outcome. Although the \(R^2\) value is very low (\(R^2\) indicates the percentage of total variation explained by the linear relationship with the predictors).
- Pearson correlation: 0.4380399
Put all the plots together
Error: `device` must be NULL, a string or a function.
PR analysis
IHC dataset
ihcPRFilter <- ihc %>%
dplyr::select(`Patient ID`
#, `Sample ID`
#, `ER Status By IHC`
#, `ER Status IHC Percent Positive`
#, `ER positivity scale used`
#, `ER positivity scale other`
#, `IHC Score`
#, `IHC-HER2`
#, `PR positivity scale used`
, `PR status by ihc`
, `PR status ihc percent positive`
) %>%
dplyr::filter(!is.na(`PR status by ihc`)) %>% # Remove the <NA>
dplyr::filter(!is.na(`PR status ihc percent positive`)) %>% # Remove the <NA>
dplyr::rename(case_id=`Patient ID`, pr_status=`PR status by ihc`, ihc_value=`PR status ihc percent positive`)
RNA-seq dataset
The RNA-seq dataset was extracted using PTD function.!
panel_design <- data.frame(drug=""
, gene_symbol="PGR"
, alteration="expression"
, exact_alteration="up"
, mutation_specification=""
, group="")
panel <- newCancerPanel(panel_design)
panel <- getAlterations(panel, tumor_type = "brca_tcga_pub2015")
panel <- subsetAlterations(panel)
# Load data from SHIVA retrospective analaysis
#panel <- readRDS("../Temp/shiva_panel.rds")
# Fetch data
rnaseq_PR <- panel@dataFull$expression$data %>%
filter(tumor_type == "brca") %>%
filter(gene_symbol == "PGR") %>%
select(case_id, expressionValue)
Inner join datasets
# join
dfPR <- dplyr::inner_join(rnaseq_PR, ihcPRFilter, by="case_id")
Comparison analysis
Explore RNA-seq Z-score
p1 <- ggplot(dfPR, aes(x=expressionValue)) +
geom_density(kernel="gaussian") +
geom_vline(aes(xintercept=0.3, color="red")) +
labs(x="Expression z-scores", title="Rna-seq expression density plot") +
theme(legend.position = "none", plot.title=element_text(size=10))
p1
Explore ICH values
p2 <- ggplot(data=dfPR, aes(x=ihc_value)) +
geom_bar(stat = "count", position = "stack") +
labs(title="Barplot with COUNT of patients in each PR ICH expression value (from 0 to 100%)")+
theme(legend.position = "none", plot.title=element_text(size=10))
p2
Compare
p3 <- ggplot(data=dfPR, aes(x=ihc_value, y=expressionValue, group=1)) +
geom_point(colour="red", size=1, shape=21, fill="white") +
labs(title="Comparison between RNA-seq and IHC values for PR in Breast cancer") +
xlab("IHC value") +
ylab("RNA-seq z-score") +
geom_smooth(method="lm") +
geom_hline(yintercept =0.3) +
theme(legend.position = "none", plot.title=element_text(size=10))
ggplotly(p3,width = 650, height = 400, margin(t=1000))
Fit to a linear model
# Convert chategorical values to continue numerical value
# <10% = 1
# 10-19% = 2
# etc..
dfPR$ihc_value2 <- as.numeric(factor(dfPR$ihc_value))
# Fit the data into a linea regressino model ache chek the coefficients
summary(lm(expressionValue ~ ihc_value2, dfPR))
Put all the plots together
LS0tCnRpdGxlOiAiQ29tcGFyaXNvbiBiZXR3ZWVuIFJOQS1zZXEgYW5kIEltbXVub2hpc3RvY2hlbWlzdHJ5IGRhdGEiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBmaWdfaGVpZ2h0OiA4CiAgICBmaWdfd2lkdGg6IDEwCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sKICAgIHRoZW1lOiByZWFkYWJsZQogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgdG9jX2Zsb2F0OiB5ZXMKICBodG1sX25vdGVib29rOiBkZWZhdWx0Ci0tLQoKV2UgYXJlIHVzaW5nIHRoZSBTSElWQSB0cmlhbCB0byBydW4gYSByZXRyb3NwZWN0aXZlIGFuYWx5c2lzIHRvIHZhbGlkYXRlIHRoZSBQVEQgcGFja2FnZS4gRHVyaW5nIHRoZSB0cmlhbCwgdGhlIGhvcm1vbiByZWNlcHRvcnMgRVIsIEFSIGFuZCBQUiB3ZXJlIGNvbGVsY3RlZCB1c2luZyBJbW11bm9oaXN0b2NoZW1pc3RyeSAoSUhDKS4gSW4gdGhlIHJldHJvc3BlY3RpdmUgYW5hbGlzaSB3ZSB1c2VkIHRoZSBleHByZXNzaW9uIChhcyB6LXNjb3JlKSB2YWx1ZXMgY29sbGVjdGVkIGZyb20gdGhlIFJOQS1zZXEgZGF0YSBUQ0dBIGRhdGFzZXQuIEluIHRoaXMgc2VjdGlvbiB3ZSB3YW50IHRvIGV4cGxvcmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIFJOQS1zZXEgYW5kIEltbXVub2hpc3RvY2hlbWlzdHJ5IGFuZCwgcG9zc2libHksIGlkZW50aWZ5IGEgImVudHJhbmNlIiB0aHJlc2hvbGQgdGhhdCB3ZSBjYW4gdXNlIGluIHRoZSBzaW11bGF0aW9uLgoKISEhRVhQTEFJTiBCRVRURVIgSEVSRSEhIQoKQ29tcGFyYXRpdmUgYW5hbHlzaXMgey50YWJzZXR9Cj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CgoKVG8gcnVuIHRoZSBjb21wYXJpc29uIGFuYWx5c2lzIHdlIHdpbGwgbmVlZCB0d28gZGF0YXNldHM6CgoqIERhdGFzZXQgd2l0aCBJSEMgdmFsdWVzLCAKKiBEYXRhc2V0IHdpdGggUk5BLXNlcSBleHByZXNpc29uIHZhbHVlcwoKQm90aCBkYXRhc2V0IG5lZWQgdG8gaGF2ZSBpbiBjb21tb24gdGhlIHNhbWUgcGF0aWVudHMgc28gdGhhdCB3ZSBjYW4gcmVjb25zdHJ1Y3QgdGhlIGluZGV4LgoKVGhlIGFuYWx5c2lzIHdpbGwgYmUgcnVuIG9uIHR3byBob3Jtb24gcmVjZXB0b3M6IAoKKiBFUgoqIFBSCgoKRVIgYW5hbHlzaXMgCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMgSUhDIGRhdGFzZXQKCkFzIElucHV0IGRhdGFzZXQgd2UgYXJlIGNob29zaW5nIHRvIHVzZTogCgpDbGluaWNhbCBkYXRhIGRvd25sb2FkZWQgZnJvbSBjQmlvcG9ydGFsIGZvciB0aGUgZGF0YXNldDogKipCcmVhc3QgSW52YXNpdmUgQ2FyY2lub21hIChUQ0dBLCBDZWxsIDIwMTUpKiogLSBbTElOS10oaHR0cHM6Ly9naXQuaWVvLmV1L2FjYy1iaW9pbmZvL21ldGEvYWN0aXZpdHkpCgpUaGUgZGF0YXNldCBoYXMgYmVlbiBkb3dubG9hZGUgYW5kIHN0b3JlZCBhcyAgYGBgYnJjYV90Y2dhX3B1YjIwMTVfY2xpbmljYWxfZGF0YS50c3ZgYGAuIAoKYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoUHJlY2lzaW9uVHJpYWxEZXNpZ25lcikKCmloYyA8LXJlYWRyOjpyZWFkX3RzdigiLi4vZXh0ZXJuYWxfcmVzb3VyY2VzL2JyY2FfdGNnYV9wdWIyMDE1X2NsaW5pY2FsX2RhdGEudHN2IikKaWhjRmlsdGVyIDwtIGloYyAlPiUgCiAgZHBseXI6OnNlbGVjdChgUGF0aWVudCBJRGAKICAgICAgICAgICAgICAgICMsIGBTYW1wbGUgSURgCiAgICAgICAgICAgICAgICAsIGBFUiBTdGF0dXMgQnkgSUhDYAogICAgICAgICAgICAgICAgLCBgRVIgU3RhdHVzIElIQyBQZXJjZW50IFBvc2l0aXZlYAogICAgICAgICAgICAgICAgIywgYEVSIHBvc2l0aXZpdHkgc2NhbGUgdXNlZGAKICAgICAgICAgICAgICAgICMsIGBFUiBwb3NpdGl2aXR5IHNjYWxlIG90aGVyYAogICAgICAgICAgICAgICAgIywgYElIQyBTY29yZWAKICAgICAgICAgICAgICAgICMsIGBJSEMtSEVSMmAKICAgICAgICAgICAgICAgICMsIGBQUiBwb3NpdGl2aXR5IHNjYWxlIHVzZWRgCiAgICAgICAgICAgICAgICAjLCBgUFIgc3RhdHVzIGJ5IGloY2AKICAgICAgICAgICAgICAgICMsIGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgCiAgICAgICAgICAgICAgICApICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBFUiBTdGF0dXMgQnkgSUhDYCkpICU+JSAjIFJlbW92ZSB0aGUgPE5BPgogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgKSkgJT4lICMgUmVtb3ZlIHRoZSA8TkE+CiAgZHBseXI6OnJlbmFtZShjYXNlX2lkPWBQYXRpZW50IElEYCwgZXJfc3RhdHVzPWBFUiBTdGF0dXMgQnkgSUhDYCwgaWhjX3ZhbHVlPWBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgKQogCiMgcHJldmlldwprYWJsZShoZWFkKGloY0ZpbHRlciksIGNhcHRpb249InRvcCA2IHJvd3MiKQpgYGAKCgojIyMgUk5BLXNlcSBkYXRhc2V0CgpUaGUgUk5BLXNlcSBkYXRhc2V0IHdhcyBleHRyYWN0ZWQgdXNpbmcgUFREIGZ1bmN0aW9uLiEKCmBgYHtyfQpwYW5lbF9kZXNpZ24gPC0gZGF0YS5mcmFtZShkcnVnPSIiCiAgICAsIGdlbmVfc3ltYm9sPSJFU1IxIgogICAgLCBhbHRlcmF0aW9uPSJleHByZXNzaW9uIgogICAgLCBleGFjdF9hbHRlcmF0aW9uPSJ1cCIKICAgICwJbXV0YXRpb25fc3BlY2lmaWNhdGlvbj0iIgogICAgLAlncm91cD0iIikKCgpwYW5lbCA8LSBuZXdDYW5jZXJQYW5lbChwYW5lbF9kZXNpZ24pCnBhbmVsIDwtIGdldEFsdGVyYXRpb25zKHBhbmVsLCB0dW1vcl90eXBlID0gImJyY2FfdGNnYV9wdWIyMDE1IikKcGFuZWwgPC0gc3Vic2V0QWx0ZXJhdGlvbnMocGFuZWwpCgojIExvYWQgZGF0YSBmcm9tIFNISVZBIHJldHJvc3BlY3RpdmUgYW5hbGF5c2lzCiNwYW5lbCA8LSByZWFkUkRTKCIuLi9UZW1wL3NoaXZhX3BhbmVsLnJkcyIpCgojIEZldGNoIGRhdGEKcm5hc2VxIDwtIHBhbmVsQGRhdGFGdWxsJGV4cHJlc3Npb24kZGF0YSAlPiUKICBmaWx0ZXIodHVtb3JfdHlwZSA9PSAiYnJjYSIpICU+JQogIGZpbHRlcihnZW5lX3N5bWJvbCA9PSAiRVNSMSIpICU+JQogIHNlbGVjdChjYXNlX2lkLCBleHByZXNzaW9uVmFsdWUpCgojIFByZXZpZXcKa2FibGUoaGVhZChybmFzZXEpLCBjYXB0aW9uID0gInRvcCA2IHJvd3MiKQpgYGAKCgojIyMgSW5uZXIgSm9pbiBkYXRhc2V0cwoKYGBge3J9CmRmIDwtIGRwbHlyOjppbm5lcl9qb2luKHJuYXNlcSwgaWhjRmlsdGVyLCBieT0iY2FzZV9pZCIpCkRUOjpkYXRhdGFibGUoZGYKICAgICAgICAgICMgQUREIEJVVFRPTlMgVE8gVEhFIFRBQkxFCiAgICAgICAgICAsIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycKICAgICAgICAgICwgb3B0aW9ucyA9IGxpc3QoCiAgICAgICAgICAgICAgIGRvbSA9ICdsQmZydGlwJwogICAgICAgICAgICAgICwgYnV0dG9ucyA9IGMoJ2NvcHknLCAnY3N2JywgJ2V4Y2VsJykKICAgICAgICAgICAgICApCiAgICAgICAgICAsIGNhcHRpb24gPSAiQ29tcGFyaXNvbiBiZXR3ZWVuIE1pc3NpbmcgYW5kIFN1Ym1pdHRlZCByZWdpb25zIChicCkgaW4gdGhlIHBhbmVsIgogICAgICAgICAgKQpgYGAKCgojIyMgQ29tcGFyaXNvbiBBbmFseXNpcwoKCgojIyMjIEV4cGxvcmUgUk5BLXNlcSBaLXNjb3JlIAoKYGBge3J9CiMgZXhwbG9yZSB6LXNjb3JlIHZhbHVlCnAxIDwtIGdncGxvdChkZiwgYWVzKHg9ZXhwcmVzc2lvblZhbHVlKSkgKwogICAgICAgIGdlb21fZGVuc2l0eShrZXJuZWw9ImdhdXNzaWFuIikgKyAKICAgICAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0PTAuMywgY29sb3I9InJlZCIpKSArIAogICAgICAgIGxhYnMoeD0iRXhwcmVzc2lvbiB6LXNjb3JlcyIsIHRpdGxlPSJSbmEtc2VxIGV4cHJlc3Npb24gZGVuc2l0eSBwbG90IikgKyAKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpwMQoKCmdnc2F2ZShmaWxlbmFtZT0iLi4vRmlndXJlcy9maWdfZXh0cmExLnN2ZyIsIHBsb3Q9cDEsIGRldmljZSA9ICJzdmciKQpgYGAKCiMjIyMgRXhwbG9yZSBJQ0ggdmFsdWVzCgpgYGB7cn0KIyBiYXJwbG90IApwMiA8LSBnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9aWhjX3ZhbHVlKSkgKyAKICAgICAgICBnZW9tX2JhcihzdGF0ID0gImNvdW50IiwgcG9zaXRpb24gPSAic3RhY2siKSArIAogICAgICAgIGxhYnModGl0bGU9IkJhcnBsb3Qgd2l0aCBDT1VOVCBvZiBwYXRpZW50cyBpbiBlYWNoIEVSIElDSCBleHByZXNzaW9uIHZhbHVlIChmcm9tIDAgdG8gMTAwJSkiKSsKICAgICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpwMgoKZ2dzYXZlKGZpbGVuYW1lPSIuLi9GaWd1cmVzL2ZpZ19leHRyYTIuc3ZnIiwgcGxvdD1wMiwgZGV2aWNlID0gInN2ZyIpCmBgYAoKCiMjIyMgQ29tcGFyZQoKYGBge3IsIGZpZy53aWR0aD03fQpwMyA8LSBnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9aWhjX3ZhbHVlLCB5PWV4cHJlc3Npb25WYWx1ZSwgZ3JvdXA9MSkpICsKICAgIGdlb21fcG9pbnQoY29sb3VyPSJyZWQiLCBzaXplPTEsIHNoYXBlPTIxLCBmaWxsPSJ3aGl0ZSIpICsKICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gYmV0d2VlbiBSTkEtc2VxIGFuZCBJSEMgdmFsdWVzIGZvciBFUiBpbiBCcmVhc3QgY2FuY2VyIikgKwogICAgeGxhYigiSUhDIHZhbHVlIikgKwogICAgeWxhYigiUk5BLXNlcSB6LXNjb3JlIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9MC4zKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKZ2dwbG90bHkocDMsd2lkdGggPSA2NTAsIGhlaWdodCA9IDQwMCwgbWFyZ2luKHQ9MTAwMCkpCgpnZ3NhdmUoZmlsZW5hbWU9Ii4uL0ZpZ3VyZXMvZmlnX2V4dHJhMy5zdmciLCBwbG90PXAzLCBkZXZpY2UgPSAic3ZnIikKYGBgCgoKIyMjIyBGaXQgdG8gYSBsaW5lYXIgbW9kZWwKCgpgYGB7cn0KIyBDb252ZXJ0IGNoYXRlZ29yaWNhbCB2YWx1ZXMgdG8gY29udGludWUgbnVtZXJpY2FsIHZhbHVlIAojIDwxMCUgPSAxCiMgMTAtMTklID0gMgojIGV0Yy4uCmRmJGloY192YWx1ZTIgPC0gYXMubnVtZXJpYyhmYWN0b3IoZGYkaWhjX3ZhbHVlKSkKIyBGaXQgdGhlIGRhdGEgaW50byBhIGxpbmVhIHJlZ3Jlc3Npbm8gbW9kZWwgYWNoZSBjaGVrIHRoZSBjb2VmZmljaWVudHMKc3VtbWFyeShsbShkZiRleHByZXNzaW9uVmFsdWUgfiBpaGNfdmFsdWUyLCBkZikpCmBgYAoKVGhlcmUgaXMgYSBzaWduaWZpY2FudCBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHByZWRpY3RvciBhbmQgdGhlIG91dGNvbWUuIEFsdGhvdWdoIHRoZSAkUl4yJCB2YWx1ZSBpcyB2ZXJ5IGxvdyAoJFJeMiQgaW5kaWNhdGVzIHRoZSBwZXJjZW50YWdlIG9mIHRvdGFsIHZhcmlhdGlvbiBleHBsYWluZWQgYnkgdGhlIGxpbmVhciByZWxhdGlvbnNoaXAgd2l0aCB0aGUgcHJlZGljdG9ycykuIAoKKiAgUGVhcnNvbiBjb3JyZWxhdGlvbjogKipgciBjb3IoYXMubnVtZXJpYyhkZiRpaGNfdmFsdWUyKSwgZGYkZXhwcmVzc2lvblZhbHVlKWAqKgoKIyMjIFB1dCBhbGwgdGhlIHBsb3RzIHRvZ2V0aGVyCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGdyaWQpCmxpYnJhcnkoZ3JpZEV4dHJhKQpncmlkLm5ld3BhZ2UoKQpwdXNoVmlld3BvcnQodmlld3BvcnQobGF5b3V0ID0gZ3JpZC5sYXlvdXQoMiwgMikpKQoKcHJpbnQocDEgKyBjb29yZF9mbGlwKCksIHZwID0gdmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAxLCBsYXlvdXQucG9zLmNvbCA9IDEpKQpwcmludChwMywgdnAgPSB2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEsIGxheW91dC5wb3MuY29sID0gMikpCnByaW50KHAyLCB2cCA9IHZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMiwgbGF5b3V0LnBvcy5jb2wgPSAyKSkKYGBgCgoKUFIgYW5hbHlzaXMKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyBJSEMgZGF0YXNldAoKYGBge3J9CmloY1BSRmlsdGVyIDwtIGloYyAlPiUgCiAgZHBseXI6OnNlbGVjdChgUGF0aWVudCBJRGAKICAgICAgICAgICAgICAgICMsIGBTYW1wbGUgSURgCiAgICAgICAgICAgICAgICAjLCBgRVIgU3RhdHVzIEJ5IElIQ2AKICAgICAgICAgICAgICAgICMsIGBFUiBTdGF0dXMgSUhDIFBlcmNlbnQgUG9zaXRpdmVgCiAgICAgICAgICAgICAgICAjLCBgRVIgcG9zaXRpdml0eSBzY2FsZSB1c2VkYAogICAgICAgICAgICAgICAgIywgYEVSIHBvc2l0aXZpdHkgc2NhbGUgb3RoZXJgCiAgICAgICAgICAgICAgICAjLCBgSUhDIFNjb3JlYAogICAgICAgICAgICAgICAgIywgYElIQy1IRVIyYAogICAgICAgICAgICAgICAgIywgYFBSIHBvc2l0aXZpdHkgc2NhbGUgdXNlZGAKICAgICAgICAgICAgICAgICwgYFBSIHN0YXR1cyBieSBpaGNgCiAgICAgICAgICAgICAgICAsIGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgCiAgICAgICAgICAgICAgICApICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBQUiBzdGF0dXMgYnkgaWhjYCkpICU+JSAjIFJlbW92ZSB0aGUgPE5BPgogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKGBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgKSkgJT4lICMgUmVtb3ZlIHRoZSA8TkE+CiAgZHBseXI6OnJlbmFtZShjYXNlX2lkPWBQYXRpZW50IElEYCwgcHJfc3RhdHVzPWBQUiBzdGF0dXMgYnkgaWhjYCwgaWhjX3ZhbHVlPWBQUiBzdGF0dXMgaWhjIHBlcmNlbnQgcG9zaXRpdmVgKQpgYGAKCiMjIyBSTkEtc2VxIGRhdGFzZXQKClRoZSBSTkEtc2VxIGRhdGFzZXQgd2FzIGV4dHJhY3RlZCB1c2luZyBQVEQgZnVuY3Rpb24uIQoKYGBge3J9CnBhbmVsX2Rlc2lnbiA8LSBkYXRhLmZyYW1lKGRydWc9IiIKICAgICwgZ2VuZV9zeW1ib2w9IlBHUiIKICAgICwgYWx0ZXJhdGlvbj0iZXhwcmVzc2lvbiIKICAgICwgZXhhY3RfYWx0ZXJhdGlvbj0idXAiCiAgICAsCW11dGF0aW9uX3NwZWNpZmljYXRpb249IiIKICAgICwJZ3JvdXA9IiIpCgoKcGFuZWwgPC0gbmV3Q2FuY2VyUGFuZWwocGFuZWxfZGVzaWduKQpwYW5lbCA8LSBnZXRBbHRlcmF0aW9ucyhwYW5lbCwgdHVtb3JfdHlwZSA9ICJicmNhX3RjZ2FfcHViMjAxNSIpCnBhbmVsIDwtIHN1YnNldEFsdGVyYXRpb25zKHBhbmVsKQoKIyBMb2FkIGRhdGEgZnJvbSBTSElWQSByZXRyb3NwZWN0aXZlIGFuYWxheXNpcwojcGFuZWwgPC0gcmVhZFJEUygiLi4vVGVtcC9zaGl2YV9wYW5lbC5yZHMiKQojIEZldGNoIGRhdGEKcm5hc2VxX1BSIDwtIHBhbmVsQGRhdGFGdWxsJGV4cHJlc3Npb24kZGF0YSAlPiUKICBmaWx0ZXIodHVtb3JfdHlwZSA9PSAiYnJjYSIpICU+JQogIGZpbHRlcihnZW5lX3N5bWJvbCA9PSAiUEdSIikgJT4lCiAgc2VsZWN0KGNhc2VfaWQsIGV4cHJlc3Npb25WYWx1ZSkKYGBgCgojIyMgSW5uZXIgam9pbiBkYXRhc2V0cwoKYGBge3J9CiMgam9pbgpkZlBSIDwtIGRwbHlyOjppbm5lcl9qb2luKHJuYXNlcV9QUiwgaWhjUFJGaWx0ZXIsIGJ5PSJjYXNlX2lkIikKYGBgCgoKIyMjIENvbXBhcmlzb24gYW5hbHlzaXMKCiMjIyMgRXhwbG9yZSBSTkEtc2VxIFotc2NvcmUgCgpgYGB7cn0KcDEgPC0gZ2dwbG90KGRmUFIsIGFlcyh4PWV4cHJlc3Npb25WYWx1ZSkpICsKICAgICAgICBnZW9tX2RlbnNpdHkoa2VybmVsPSJnYXVzc2lhbiIpICsgCiAgICAgICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdD0wLjMsIGNvbG9yPSJyZWQiKSkgKyAKICAgICAgICBsYWJzKHg9IkV4cHJlc3Npb24gei1zY29yZXMiLCB0aXRsZT0iUm5hLXNlcSBleHByZXNzaW9uIGRlbnNpdHkgcGxvdCIpICsgCiAgICAgICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTEwKSkKcDEKYGBgCgoKIyMjIyBFeHBsb3JlIElDSCB2YWx1ZXMKCmBgYHtyfQpwMiA8LSBnZ3Bsb3QoZGF0YT1kZlBSLCBhZXMoeD1paGNfdmFsdWUpKSArIAogICAgICAgIGdlb21fYmFyKHN0YXQgPSAiY291bnQiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsgCiAgICAgICAgbGFicyh0aXRsZT0iQmFycGxvdCB3aXRoIENPVU5UIG9mIHBhdGllbnRzIGluIGVhY2ggUFIgSUNIIGV4cHJlc3Npb24gdmFsdWUgKGZyb20gMCB0byAxMDAlKSIpKwogICAgICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMCkpCnAyCmBgYAoKCgojIyMjIENvbXBhcmUKCmBgYHtyLCBmaWcud2lkdGg9N30KcDMgPC0gZ2dwbG90KGRhdGE9ZGZQUiwgYWVzKHg9aWhjX3ZhbHVlLCB5PWV4cHJlc3Npb25WYWx1ZSwgZ3JvdXA9MSkpICsKICAgIGdlb21fcG9pbnQoY29sb3VyPSJyZWQiLCBzaXplPTEsIHNoYXBlPTIxLCBmaWxsPSJ3aGl0ZSIpICsKICAgIGxhYnModGl0bGU9IkNvbXBhcmlzb24gYmV0d2VlbiBSTkEtc2VxIGFuZCBJSEMgdmFsdWVzIGZvciBQUiBpbiBCcmVhc3QgY2FuY2VyIikgKwogICAgeGxhYigiSUhDIHZhbHVlIikgKwogICAgeWxhYigiUk5BLXNlcSB6LXNjb3JlIikgKwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9MC4zKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTApKQoKZ2dwbG90bHkocDMsd2lkdGggPSA2NTAsIGhlaWdodCA9IDQwMCwgbWFyZ2luKHQ9MTAwMCkpCmBgYAoKCiMjIyMgRml0IHRvIGEgbGluZWFyIG1vZGVsCgpgYGB7cn0KIyBDb252ZXJ0IGNoYXRlZ29yaWNhbCB2YWx1ZXMgdG8gY29udGludWUgbnVtZXJpY2FsIHZhbHVlIAojIDwxMCUgPSAxCiMgMTAtMTklID0gMgojIGV0Yy4uCmRmUFIkaWhjX3ZhbHVlMiA8LSBhcy5udW1lcmljKGZhY3RvcihkZlBSJGloY192YWx1ZSkpCiMgRml0IHRoZSBkYXRhIGludG8gYSBsaW5lYSByZWdyZXNzaW5vIG1vZGVsIGFjaGUgY2hlayB0aGUgY29lZmZpY2llbnRzCnN1bW1hcnkobG0oZXhwcmVzc2lvblZhbHVlIH4gaWhjX3ZhbHVlMiwgZGZQUikpCmBgYAoKIyMjIFB1dCBhbGwgdGhlIHBsb3RzIHRvZ2V0aGVyCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyLCBlY2hvPUZBTFNFfQpsaWJyYXJ5KGdyaWQpCmdyaWQubmV3cGFnZSgpCnB1c2hWaWV3cG9ydCh2aWV3cG9ydChsYXlvdXQgPSBncmlkLmxheW91dCgyLCAyKSkpCgpwcmludChwMSArIGNvb3JkX2ZsaXAoKSwgdnAgPSB2aWV3cG9ydChsYXlvdXQucG9zLnJvdyA9IDEsIGxheW91dC5wb3MuY29sID0gMSkpCnByaW50KHAzLCB2cCA9IHZpZXdwb3J0KGxheW91dC5wb3Mucm93ID0gMSwgbGF5b3V0LnBvcy5jb2wgPSAyKSkKcHJpbnQocDIsIHZwID0gdmlld3BvcnQobGF5b3V0LnBvcy5yb3cgPSAyLCBsYXlvdXQucG9zLmNvbCA9IDIpKQoKYGBg